import bisect
import uuid

import redis.exceptions
from redis.client import Redis

mconn = Redis(host="192.168.35.110", port=6379, db=0, decode_responses=True)


def add_update_contact(conn, user, contact):
    ac_list = 'recent:' + user
    pipeline = conn.pipeline(True)
    pipeline.lrem(ac_list, 1, contact)
    pipeline.lpush(ac_list, contact)
    pipeline.ltrim(ac_list, 0, 99)
    pipeline.execute()


def remove_contact(conn, user, contact):
    conn.lrem('recent:' + user, 1, contact)


def fetch_autocomplete_list(conn, user, prefix):
    candidates = conn.lrange('recent:' + user, 0, -1)
    matches = []
    for candidate in candidates:
        if candidate.lower().startswith(prefix):
            matches.append(candidate)
    return matches


valid_characters = '`abcdefghijklmnopqrstuvwxyz{'


def find_prefix_range(prefix):
    posn = bisect.bisect_left(valid_characters, prefix[-1:])
    suffix = valid_characters[(posn or 1) - 1]
    return prefix[:-1] + suffix + '{', prefix + '{'


def autocomplete_on_prefix(conn, guid, prefix):
    start, end = find_prefix_range(prefix)
    identifier = str(uuid.uuid4())
    start += identifier
    end += identifier
    zset_name = 'members:' + guid
    conn.zadd(zset_name, {start: 0, end: 0})
    pipeline = conn.pipeline(True)
    while 1:
        try:
            pipeline.watch(zset_name)
            sindex = pipeline.zrank(zset_name, start)
            eindex = pipeline.zrank(zset_name, end)
            erange = min(sindex + 9, eindex - 2)
            pipeline.multi()
            pipeline.zrem(zset_name, start, end)
            pipeline.zrange(zset_name, sindex, erange)
            items = pipeline.execute()[-1]
            break;
        except redis.exceptions.WatchError:
            continue
    return [item for item in items if '{' not in item]


def print_hi(name):
    # 在下面的代码行中使用断点来调试脚本。
    print(f'Hi, {name}')  # 按 Ctrl+F8 切换断点。


# 按间距中的绿色按钮以运行脚本。
if __name__ == '__main__':
    add_update_contact(mconn, 'hyman', 'tom')
    add_update_contact(mconn, 'hyman', 'tim')
    add_update_contact(mconn, 'hyman', 'terry')
    remove_contact(mconn, 'hyman', 'jerry')
    print(fetch_autocomplete_list(mconn, 'hyman', 't'))
    print(find_prefix_range('hyman'))
    mconn.zadd('members:email', {'hyman1': 0, 'hyman2': 0})
    mconn.zadd('members:email', {'tom': 0, 'jerry': 0})
    mconn.zadd('members:email', {'ami': 0, 'bob': 0})
    print(autocomplete_on_prefix(mconn, 'email', 'hyman'))
    print_hi('PyCharm')

# 访问 https://www.jetbrains.com/help/pycharm/ 获取 PyCharm 帮助
